package org.ricks.net.http.restful;

import org.ricks.ioc.RicksContext;
import org.ricks.net.http.logging.Logger;
import org.ricks.net.http.logging.LoggerFactory;
import org.ricks.net.http.restful.handler.RestfulHandler;
import org.ricks.net.http.server.HttpBootstrap;
import org.ricks.net.http.server.HttpRequest;
import org.ricks.net.http.server.HttpResponse;
import org.ricks.net.http.server.HttpServerHandler;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;

/**
 * @author 三刀（zhengjunweimail@163.com）
 * @version V1.0 , 2022/7/2
 */
public class RestfulBootstrap {

    private static final Logger LOGGER = LoggerFactory.getLogger(RestfulBootstrap.class);
    private static final List<Object> controllers = new ArrayList<>();
    private final HttpBootstrap httpBootstrap = new HttpBootstrap() {
        @Override
        public void start() {
            try {
                controllers.forEach(restfulHandler::addInterceptor);
                controllers.forEach(restfulHandler::addController);
            } catch (Exception e) {
                throw new IllegalStateException("start application exception", e);
            }

            super.start();
        }

        @Override
        public void shutdown() {
            super.shutdown();
        }
    };
    private final RestfulHandler restfulHandler;

    private static final HttpServerHandler DEFAULT_HANDLER = new HttpServerHandler() {
        private final byte[] BYTES = "hello smart-http-rest".getBytes();

        @Override
        public void handle(HttpRequest request, HttpResponse response) throws IOException {
            response.getOutputStream().write(BYTES);
        }
    };

    private RestfulBootstrap(HttpServerHandler defaultHandler) {
        if (defaultHandler == null) {
            throw new NullPointerException();
        }
        this.restfulHandler = new RestfulHandler(defaultHandler);
        httpBootstrap.httpHandler(restfulHandler);
    }


    public void addController(Class<?> clazz) {
        Constructor<?>[] constructors = clazz.getDeclaredConstructors();
        boolean suc = false;
        for (Constructor<?> constructor : constructors) {
            if (constructor.getParameters().length != 0) {
                continue;
            }
            try {
                constructor.setAccessible(true);
                Object object = constructor.newInstance();
                RicksContext.me().analytical(object).injection();
                addController(object);
                suc = true;
            } catch (Exception e) {
                throw new RuntimeException("restful注册controller实例化失败,clazz:" + clazz, e);
            }
        }
        if (!suc) {
            LOGGER.warn("no public no-args constructor found for controllerClass: {}", clazz.getName());
        }
    }

    public void addController (Object controller) {
        controllers.add(controller);
    }


    public RestfulBootstrap controller(Class<?>... classes) {
        for (Class<?> clazz : classes) {
            addController(clazz);
        }
        return this;
    }

    public static RestfulBootstrap getInstance() {
        return getInstance(DEFAULT_HANDLER);
    }

    public static RestfulBootstrap getInstance(HttpServerHandler defaultHandler) {
        return new RestfulBootstrap(defaultHandler);
    }

    public void setAsyncExecutor(ExecutorService asyncExecutor) {
        restfulHandler.setAsyncExecutor(asyncExecutor);
    }

    public HttpBootstrap bootstrap() {
        return httpBootstrap;
    }
}
